#include "n32g031.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesSPI.h"


uint8_t st_SPI1SendDMABuff[SPI1_DMA_SEND_LENGTH + 4] = {0};


void vSPI1Init(void)
{
    GPIO_InitType GPIO_InitStructure = {0};
    SPI_InitType SPI_InitStructure = {0};

    /* Enable GPIO clock for SPIy and SPIz */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_AFIO, ENABLE);

    /* Enable SPIy and SPIz Periph clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1, ENABLE);


    GPIO_InitStruct(&GPIO_InitStructure);
    /* Configure SPI1 pins: SCK, MISO and MOSI ---------------------------------*/
    /* Confugure SCK , MISO and MOSI pins as Alternate Function Push Pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_15;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.GPIO_Pull  = GPIO_NO_PULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_HIGH;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF0_SPI1;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    SET_SPI1_NSS_HIGH();


    /* SPIy Config -------------------------------------------------------------*/
    SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
    SPI_InitStructure.SpiMode       = SPI_MODE_MASTER;
    SPI_InitStructure.DataLen       = SPI_DATA_SIZE_8BITS;
    SPI_InitStructure.CLKPOL        = SPI_CLKPOL_LOW;
    SPI_InitStructure.CLKPHA        = SPI_CLKPHA_SECOND_EDGE;
    SPI_InitStructure.NSS           = SPI_NSS_SOFT;
    SPI_InitStructure.BaudRatePres  = SPI_BR_PRESCALER_8;
    SPI_InitStructure.FirstBit      = SPI_FB_LSB;
    SPI_InitStructure.CRCPoly       = 7;
    SPI_Init(SPI1, &SPI_InitStructure);


    vSPI1DMAInit();


    /* Enable SPI_MASTER CRC calculation */
    SPI_EnableCalculateCrc(SPI1, ENABLE);

    /* Enable SPIy */
    SPI_Enable(SPI1, ENABLE);
}

void vSPI1DMAInit(void)
{
    DMA_InitType DMA_InitStructure = {0};

    /* Enable DMA clock */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);


    /* SPI_MASTER_TX_DMA_CHANNEL configuration
     * ---------------------------------*/
    DMA_DeInit(DMA_CH3);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&SPI1->DAT;
    DMA_InitStructure.MemAddr        = (uint32_t)st_SPI1SendDMABuff;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;
    DMA_InitStructure.BufSize        = SPI1_DMA_SEND_LENGTH;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;
    DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;
    DMA_InitStructure.Priority       = DMA_PRIORITY_LOW;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(DMA_CH3, &DMA_InitStructure);
    DMA_RequestRemap(DMA_REMAP_SPI1_RX, DMA, DMA_CH3,ENABLE);

    /* Enable SPI_MASTER DMA Tx request */
    SPI_I2S_EnableDma(SPI1, SPI_I2S_DMA_TX, ENABLE);

    /* Enable DMA channels */
    DMA_EnableChannel(DMA_CH3, ENABLE);
}

uint8_t ucSPIWriteReadByte(SPI_Module* SPIx, uint8_t ucByte)
{
    while(RESET == SPI_I2S_GetStatus(SPIx, SPI_I2S_TE_FLAG));
    SPI_I2S_TransmitData(SPIx, ucByte);

    while(RESET == SPI_I2S_GetStatus(SPIx, SPI_I2S_RNE_FLAG));
    ucByte = SPI_I2S_ReceiveData(SPIx);

    return ucByte;
}

int8_t cSPIWriteDatas(SPI_Module* SPIx, uint8_t *pBuffer, int32_t iLength)
{
    int8_t cError = 0;

    if(pBuffer == NULL)
        return -1;

    while((iLength--) > 0)
    {
        while(RESET == SPI_I2S_GetStatus(SPIx, SPI_I2S_TE_FLAG));
        SPI_I2S_TransmitData(SPIx, *pBuffer++);
    }

    return cError;
}

int8_t cSPIReadDatas(SPI_Module* SPIx, uint8_t *pBuffer, int32_t iLength)
{
    int8_t cError = 0;

    if(pBuffer == NULL)
        return -1;

    while((iLength--) > 0)
    {
        while(RESET == SPI_I2S_GetStatus(SPIx, SPI_I2S_TE_FLAG));
        SPI_I2S_TransmitData(SPIx, 0xFFFF);

        while(RESET == SPI_I2S_GetStatus(SPIx, SPI_I2S_RNE_FLAG));
        *pBuffer++ = SPI_I2S_ReceiveData(SPIx);
    }

    return cError;
}
